<!--
 * @Author: jhw
 * @Date: 2025-08-07 00:11:52
 * @LastEditors: jhw
 * @LastEditTime: 2025-08-22 16:54:42
 * @Description:
-->
<template>
  <div
    ref="centerContainerRef"
    class="center-container"
    @dragover="handleDragOver"
    @drop="handleDrop"
    @dragleave="handleDragLeave"
  >
    <div
      v-if="coms.length === 0"
      class="text-gray-500 text-2xl flex items-center justify-center h-200px"
    >
      请将左侧组件拖拽到此处
    </div>
    <Vuedraggable
      v-model="coms"
      itemKey="index"
      :disabled="type === 'detail'"
      @start="handleStart"
      @end="handleEnd"
    >
      <template #item="{ element, index }">
        <div
          class="content relative mb-10px"
          :class="{ active: currentComponentIndex === index }"
          :ref="(el) => (componentRefs[index] = el)"
          @click="handleCurrentClick(index)"
        >
          <component
            :is="element.type"
            :componentId="element.id"
            :status="element.status"
            :serialNum="serialNum[index]"
          />
          <div class="absolute delete-btn" v-show="currentComponentIndex === index">
            <el-button
              type="danger"
              class="ml-10"
              size="small"
              :icon="Close"
              circle
              @click.stop="removeCom(index)"
            />
          </div>
        </div>
      </template>
    </Vuedraggable>
  </div>
</template>

<script setup lang="ts">
import { useEditorStore } from '@/stores/useEditor';
import emitter from '@/utils/eventBus';
import { useSerialNum } from '@/utils/hooks';
import { Close } from '@element-plus/icons-vue';
import { computed, nextTick, ref, useTemplateRef, type ComponentPublicInstance } from 'vue';
import Vuedraggable from 'vuedraggable';
import { defaultStatusMap } from '@/configs/defaultStatus/defaultStatusMap';
import type { MaterialItem, Status, SurveyComName } from '@/types';
import { updateInitStatusBeforeAdd } from '@/utils';
import { useRoute } from 'vue-router';

const editorStore = useEditorStore();
const route = useRoute();
const type = route.query.type as string; // 问卷类型
const centerContainerRef = useTemplateRef('centerContainerRef');
const componentRefs = ref<(HTMLElement | null | ComponentPublicInstance | Element)[]>([]);
const coms = computed({
  get() {
    return editorStore.coms;
  },
  set(value) {
    editorStore.coms = value;
  },
});
const currentComponentIndex = computed(() => editorStore.currentComponentIndex);
const serialNum = computed(() => useSerialNum(coms.value).value);

// 滚动到最底部
const scrollToBottom = () => {
  nextTick(() => {
    window.scrollTo({
      top: centerContainerRef.value?.scrollHeight,
      behavior: 'smooth',
    });
  });
};

// 滚动到指定组件
const scrollToComponent = (index: number) => {
  nextTick(() => {
    (componentRefs.value[index] as HTMLElement)?.scrollIntoView({
      behavior: 'smooth',
      block: 'center',
    });
  });
};

emitter.on('scrollToBottom', scrollToBottom);
emitter.on('scrollToComponent', scrollToComponent);

const handleCurrentClick = (index: number) => {
  if (type === 'detail') return;
  // 如果点击的是当前组件，重置-1
  if (currentComponentIndex.value === index) {
    editorStore.setCurrentComponentIndex(-1);
  } else {
    editorStore.setCurrentComponentIndex(index);
    scrollToComponent(index);
  }
};

const removeCom = (index: number) => {
  editorStore.removeCom(index);
};

const handleStart = () => {
  editorStore.setCurrentComponentIndex(-1);
};

const handleEnd = () => {};

// 处理拖拽悬停
const handleDragOver = (event: DragEvent) => {
  event.preventDefault(); // 阻止默认行为
  if (event.dataTransfer) {
    event.dataTransfer.dropEffect = 'copy';
  }

  // 显示拖拽位置指示器
  showDropIndicator(event);
};

// 处理拖拽放置
const handleDrop = (event: DragEvent) => {
  event.preventDefault();

  // 清除拖拽指示器
  removeDropIndicator();

  if (event.dataTransfer) {
    try {
      const data = event.dataTransfer.getData('application/json');
      if (data) {
        const item: MaterialItem = JSON.parse(data);
        const newName = item.materialName as SurveyComName;
        const defaultStatus = defaultStatusMap[newName]() as Status;
        updateInitStatusBeforeAdd(defaultStatus, newName);

        // 计算插入位置
        const insertIndex = calculateInsertIndex(event);
        if (insertIndex !== -1) {
          // 在指定位置插入组件
          editorStore.insertCom(defaultStatus, insertIndex);
        } else {
          // 如果没有找到合适的位置，添加到末尾
          editorStore.addCom(defaultStatus);
        }
        // emitter.emit('scrollToBottom');
      }
    } catch (error) {
      console.error('Failed to parse dropped data:', error);
    }
  }
};

// 更精确的拖拽位置检测 - 使用 document.elementFromPoint
const getDropPosition = (event: DragEvent): number | null => {
  if (!centerContainerRef.value) return null;

  const mouseX = event.clientX;
  const mouseY = event.clientY;

  // 使用 document.elementFromPoint 获取鼠标下方的元素
  const elementBelowMouse = document.elementFromPoint(mouseX, mouseY);
  if (!elementBelowMouse) return coms.value.length;

  // 查找最近的组件容器
  const targetComponent = findClosestComponent(elementBelowMouse as HTMLElement);
  if (targetComponent) {
    // 获取组件索引
    const componentIndex = Array.from(
      centerContainerRef.value.querySelectorAll('.content'),
    ).indexOf(targetComponent);
    return componentIndex !== -1 ? componentIndex : coms.value.length;
  }

  return coms.value.length;
};

// 查找最近的组件容器
const findClosestComponent = (element: HTMLElement): HTMLElement | null => {
  let currentElement: HTMLElement | null = element;

  while (currentElement && currentElement !== centerContainerRef.value) {
    if (currentElement.classList.contains('content')) {
      return currentElement;
    }
    currentElement = currentElement.parentElement;
  }

  return null;
};

// 防抖相关的状态
let lastDropPosition: number | null = null;
let dropPositionTimeoutId: number;
let isCalculating = false;

// 防抖版本的拖拽位置检测
const debouncedGetDropPosition = (event: DragEvent): number | null => {
  // 如果正在计算中，返回上次的结果
  if (isCalculating) {
    return lastDropPosition;
  }

  // 清除之前的定时器
  clearTimeout(dropPositionTimeoutId);

  // 设置计算标志
  isCalculating = true;

  dropPositionTimeoutId = setTimeout(() => {
    lastDropPosition = getDropPosition(event);
    isCalculating = false;
  }, 16); // 约60fps，约60次/秒

  return lastDropPosition;
};

// 增强的拖拽位置计算
const calculateInsertIndex = (event: DragEvent): number => {
  const dropIndex = debouncedGetDropPosition(event);

  if (dropIndex === null) return coms.value.length;

  return dropIndex;
};

// 显示拖拽位置指示器 - 改进版本
const showDropIndicator = (event: DragEvent) => {
  if (!centerContainerRef.value) return;

  // 移除之前的指示器
  removeDropIndicator();

  const dropIndex = debouncedGetDropPosition(event);
  if (dropIndex === null) return;

  // 获取目标组件元素
  const componentElements = centerContainerRef.value.querySelectorAll('.content');
  const targetElement = componentElements[dropIndex] as HTMLElement;

  if (!targetElement) return;

  const componentRect = targetElement.getBoundingClientRect();
  const containerRect = centerContainerRef.value.getBoundingClientRect();

  // 创建指示器 - 统一显示在组件上方
  const indicator = document.createElement('div');
  indicator.className = 'drop-indicator';

  const indicatorTop = componentRect.top - containerRect.top;

  indicator.style.cssText = `
    position: absolute;
    left: 0;
    right: 0;
    height: 3px;
    background: linear-gradient(90deg, #409eff 0%, #67c23a 50%, #409eff 100%);
    z-index: 1000;
    pointer-events: none;
    top: ${indicatorTop}px;
    border-radius: 2px;
    box-shadow: 0 0 8px rgba(64, 158, 255, 0.8);
  `;

  centerContainerRef.value.appendChild(indicator);
};

// 移除拖拽指示器
const removeDropIndicator = () => {
  if (centerContainerRef.value) {
    const existingIndicator = centerContainerRef.value.querySelector('.drop-indicator');
    if (existingIndicator) {
      existingIndicator.remove();
    }
  }
};

// 处理拖拽离开
const handleDragLeave = () => {
  removeDropIndicator();
};
</script>

<style scoped lang="scss">
.center-container {
  @apply w-1/2 my-70px mx-auto p-20px relative;
  border: 1px solid var(--border-color);
  border-radius: var(--border-radius-md);
  background: var(--white);
  min-height: 700px; /* 确保有足够的高度来接收拖拽 */
  .content {
    @apply cursor-pointer p-10px;
    background-color: var(--white);
    border-radius: var(--border-radius-sm);
    &:hover {
      transform: scale(1.01);
      transition: 0.5s;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    }
  }
}
.active {
  transform: scale(1.01);
  transition: 0.5s;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.delete-btn {
  right: -5px;
  top: -10px;
}

.drop-indicator {
  transition: all 0.2s ease;
  box-shadow: 0 0 8px rgba(64, 158, 255, 0.6);
}
</style>
